package com.mcxx.modules.temporary.family.service.write;

import cn.hutool.core.util.IdUtil;
import com.mcxx.ansync.event.PropertiesEventHandler;
import com.mcxx.common.exception.BizException;
import com.mcxx.constant.PropertiesConstant;
import com.mcxx.modules.miniSalvation.family.dao.write.BankWriteDao;
import com.mcxx.modules.miniSalvation.family.service.write.BankWriteService;
import com.mcxx.modules.temporary.family.dao.write.TmpFamilyMemberWriteDao;
import com.mcxx.modules.temporary.family.dto.TmpFamilyMemberDTO;
import com.mcxx.modules.temporary.family.entity.TmpFamilyMainEntity;
import com.mcxx.modules.temporary.family.entity.TmpFamilyMemberEntity;
import com.mcxx.modules.temporary.family.service.read.TmpFamilyMainReadService;
import com.mcxx.modules.temporary.family.service.read.TmpFamilyMemberReadService;
import com.mcxx.modules.temporary.order.dto.TmpAuditDTO;
import com.mcxx.modules.temporary.order.dto.TmpOrderDTO;
import com.mcxx.modules.temporary.order.entity.TmpOrderEntity;
import com.mcxx.modules.temporary.order.service.read.TmpOrderReadService;
import com.mcxx.modules.temporary.order.service.write.TmpOrderWriteService;
import com.mcxx.util.CommonUtil;
import com.mcxx.util.Constant;
import com.mcxx.util.FailureCode;
import com.yinhai.ta404.core.security.vo.UserAccountVo;
import com.yinhai.ta404.core.transaction.annotation.TaTransactional;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@TaTransactional
public class TmpFamilyMemberWriteService {

    @Autowired
    private TmpFamilyMemberWriteDao tmpFamilyMemberWriteDao;
    @Autowired
    private TmpFamilyMemberReadService familyMemberReadService;
    @Autowired
    private TmpFamilyMainWriteService familyMainWriteService;
    @Autowired
    private PropertiesEventHandler propertiesEventHandler;
    @Autowired
    private TmpOrderReadService orderReadService;
    @Autowired
    private TmpOrderWriteService orderWriteService;
    @Autowired
    private BankWriteService bankWriteService;
    @Autowired
    private TmpFamilyMemberReadService tmpFamilyMemberReadService;
    @Autowired
    private TmpFamilyMainReadService tmpFamilyMainReadService;
    @Autowired
    private BankWriteDao bankWriteDao;



    public void addFamilyMember(TmpFamilyMemberEntity entity) {
        int rows = tmpFamilyMemberWriteDao.insertIgnoreNull(entity);
        if (rows < 1) {
            throw new BizException(FailureCode.ERR_9999);
        }
        propertiesEventHandler.publishAddEvent(entity, PropertiesConstant.CATE_MEMBER_CHANGE, null);
    }


    public void addFamilyMember(TmpFamilyMemberDTO dto, UserAccountVo accountVo) {

        if(Constant.DomesticRelation.ONESELF.equals(dto.getFamilyRelation())){
            String masterIdCard = orderReadService.getMasertIdcard(dto.getOrderId());
            if(StringUtils.isNotBlank(masterIdCard)&&!dto.getIdcard().equals(masterIdCard)){
                throw new BizException("-1","一个家庭只能有一个户主");
            }
        }
        TmpFamilyMainEntity mainEntity = tmpFamilyMainReadService.getById(dto.getFamilyId());
        TmpFamilyMemberEntity entity = new TmpFamilyMemberEntity();
        BeanUtils.copyProperties(dto,entity);
        entity.setId(IdUtil.simpleUUID());
        entity.setAreaCode(mainEntity.getAreaCode());
        entity.setCreateTime(new Date());
        entity.setCreateBy(accountVo.getUserId());


        addFamilyMember(entity);

        dto.setId(entity.getId());
        orderWriteService.updateMemberInfo(dto,null);

        dto.setId(entity.getId());
        bankWriteService.editTempBankInfo(dto,accountVo);

        updateOrderFamilyInfo(dto, accountVo);
    }


    public void updateFamilyMember(TmpFamilyMemberEntity entity)  {
        int rows = tmpFamilyMemberWriteDao.updateIgnoreNull(entity);
        if (rows < 1) {
            throw new BizException(FailureCode.ERR_9999);
        }
    }


    public void  updateFamilyMember(TmpFamilyMemberDTO dto, UserAccountVo accountVo) {
        String relation = tmpFamilyMemberReadService.getRelationByMemberId(dto.getId(),dto.getFamilyId());

        if(Constant.DomesticRelation.ONESELF.equals(dto.getFamilyRelation())){
            String masterIdCard = orderReadService.getMasertIdcard(dto.getOrderId());
            if(StringUtils.isNotBlank(masterIdCard)&&!dto.getIdcard().equals(masterIdCard)){
                throw new BizException("-1","一个家庭只能有一个户主");
            }
        }


        TmpFamilyMemberEntity entity = new TmpFamilyMemberEntity();
        BeanUtils.copyProperties(dto,entity);
        entity.setIsSaveObject("0");

        String applyIdcard = orderReadService.getApplyIdcard(dto.getOrderId());
        if(!CommonUtil.invalidArgs(applyIdcard) && !applyIdcard.equals(dto.getIdcard())){
            entity.setIsApply("2");
        }

        updateFamilyMember(entity);

        bankWriteService.editTempBankInfo(dto,accountVo);

        orderWriteService.updateMemberInfo(dto,relation);

        updateOrderFamilyInfo(dto, accountVo);

        if (StringUtils.isNotEmpty(dto.getSourceFamilyId()) && !dto.getFamilyId().equals(dto.getSourceFamilyId())) {
            TmpFamilyMemberDTO tmpFamilyMemberDTO = new TmpFamilyMemberDTO();
            tmpFamilyMemberDTO.setFamilyId(dto.getSourceFamilyId());


            if (Constant.DomesticRelation.ONESELF.equals(dto.getSourceFamilyRelation())) {
                List<TmpFamilyMemberEntity> sourceFamilyMembers = familyMemberReadService.listByFamilyId(dto.getSourceFamilyId());
                if (CollectionUtils.isNotEmpty(sourceFamilyMembers)) {
                    TmpFamilyMemberEntity memberEntity4Update = new TmpFamilyMemberEntity();
                    memberEntity4Update.setId(sourceFamilyMembers.get(0).getId());
                    memberEntity4Update.setFamilyRelation(Constant.DomesticRelation.ONESELF);
                    tmpFamilyMemberWriteDao.updateIgnoreNull(memberEntity4Update);

                    tmpFamilyMemberDTO.setFamilyRelation(Constant.DomesticRelation.ONESELF);
                    tmpFamilyMemberDTO.setIdcard(sourceFamilyMembers.get(0).getIdcard());
                    tmpFamilyMemberDTO.setName(sourceFamilyMembers.get(0).getName());
                }
            }


            Map<String,Integer> countMap = familyMemberReadService.countMemberNumAndSaveMemberNum(tmpFamilyMemberDTO.getFamilyId());

            familyMainWriteService.updateFamilyInfo(tmpFamilyMemberDTO, accountVo, countMap);
        }
    }


    public void updateFamilyRelation(String familyId, String idcard)  {
        int rows = tmpFamilyMemberWriteDao.updateFamilyRelation(familyId, idcard);
        if (rows < 1) {
            throw new BizException(FailureCode.ERR_9999);
        }
    }

    public void updateFamilyApply(String familyId, String idcard)  {
        int rows = tmpFamilyMemberWriteDao.updateMemberIsApply(familyId, idcard);
    }


    private void updateOrderFamilyInfo(TmpFamilyMemberDTO familyMemberDTO, UserAccountVo accountVo){

        Map<String,Integer> countMap = familyMemberReadService.countMemberNumAndSaveMemberNum(familyMemberDTO.getFamilyId());


        familyMainWriteService.updateFamilyInfo(familyMemberDTO, accountVo, countMap);

        if (StringUtils.isNotEmpty(familyMemberDTO.getOrderId())) {

            TmpOrderDTO orderDTO = orderReadService.getStateAndVersion(familyMemberDTO.getOrderId());


            orderDTO.setSaveMemberNumber(countMap.get("saveMemberCount"));
            orderWriteService.updateOrderFamilyInfo(familyMemberDTO, accountVo, orderDTO);
        }
    }


    public void delete(TmpFamilyMemberEntity entity) {
        int rows = tmpFamilyMemberWriteDao.delete(entity);
        if (rows < 1) {
            throw new BizException(FailureCode.ERR_9999.getCode(),FailureCode.ERR_9999.getMsg());
        }
    }


    public void delete(TmpFamilyMemberDTO dto, UserAccountVo accountVo) {
        TmpFamilyMemberEntity entity = familyMemberReadService.getById(dto.getId());
        if (Constant.DomesticRelation.ONESELF.equals(entity.getFamilyRelation())) {

            throw new BizException(FailureCode.ERR_9999.getCode(),"'户主不可以删除'");
        }
        if(Constant.IsApply.YES.equals(entity.getIsApply())){

            throw new BizException(FailureCode.ERR_9999.getCode(),"申请人不可以删除");
        }


        delete(entity);


        updateOrderFamilyInfo(dto, accountVo);

        propertiesEventHandler.publishDeleteEvent(entity, PropertiesConstant.CATE_MEMBER_DEL, null);
    }


    public void changeFamilyRelation(String familyId, String orderId, Map<String,String> relationshipMap) {

        TmpFamilyMemberEntity master = checkConstraint4ChangeMaster(relationshipMap);


        TmpFamilyMainEntity familyMainEntity = new TmpFamilyMainEntity();
        familyMainEntity.setId(familyId);
        familyMainEntity.setName(master.getName());
        familyMainEntity.setIdcard(master.getIdcard());
        familyMainWriteService.updateFamily(familyMainEntity);


        for (Map.Entry<String,String> entry: relationshipMap.entrySet()) {
            TmpFamilyMemberEntity entity = new TmpFamilyMemberEntity();
            entity.setId(entry.getKey());
            entity.setFamilyRelation(entry.getValue());
            tmpFamilyMemberWriteDao.updateIgnoreNull(entity);
        }


        if (StringUtils.isNotEmpty(orderId)) {
            TmpOrderEntity order = new TmpOrderEntity();
            order.setId(orderId);
            order.setName(master.getName());
            order.setMemberId(master.getId());
            order.setIdcard(master.getIdcard());
            orderWriteService.updateOrder(order);
        }
    }


    private TmpFamilyMemberEntity checkConstraint4ChangeMaster(Map<String,String> relationshipMap) {
        Map<String,Integer> countMap = new HashMap<>();
        String masterId = null;


        for (Map.Entry<String,String> entry: relationshipMap.entrySet()) {
            countMap.put(entry.getValue(),countMap.get(entry.getValue()) == null ? 1 : countMap.get(entry.getValue()) + 1);
            if (Constant.DomesticRelation.ONESELF.equals(entry.getValue())) {
                masterId = entry.getKey();
            }
        }


        if (CommonUtil.invalidArgs(masterId)) {

            throw new BizException(FailureCode.ERR_10016.getCode(),FailureCode.ERR_10016.getMessage());
        }
        if (countMap.get(Constant.DomesticRelation.ONESELF) > 1) {

            throw new BizException(FailureCode.ERR_20004.getCode(),FailureCode.ERR_20004.getMessage());
        }
        if (!CommonUtil.invalidArgs(countMap.get(Constant.DomesticRelation.SPOUSE))
                && countMap.get(Constant.DomesticRelation.SPOUSE) > 1) {

            throw new BizException(FailureCode.ERR_20030.getCode(),FailureCode.ERR_20030.getMessage());
        }

        TmpFamilyMemberEntity master = familyMemberReadService.getById(masterId);

        return master;
    }


    public void copyFromOtherSource(String familyId,String newFamilyId) {
        tmpFamilyMemberWriteDao.copyFromOtherSource(familyId,newFamilyId);
    }


    public void copyFromSplittingSource(String familyId,String newFamilyId,String memberState) {
        tmpFamilyMemberWriteDao.copyFromSplittingSource(familyId,newFamilyId,memberState);
    }


    public void updateMemberIsSaveObject(TmpAuditDTO tmpAuditDTO){
        for(TmpFamilyMemberDTO dto : tmpAuditDTO.getMemberList()){
            TmpFamilyMemberEntity tmpFamilyMember = new TmpFamilyMemberEntity();
            tmpFamilyMember.setId(dto.getId());
            tmpFamilyMember.setIsSaveObject(dto.getIsSaveObject());

            int rst = tmpFamilyMemberWriteDao.updateIgnoreNull(tmpFamilyMember);
            if(rst <= 0){
                throw new BizException(FailureCode.ERR_9999);
            }

            if(Constant.DomesticRelation.ONESELF.equals(dto.getFamilyRelation())){

                tmpAuditDTO.setMasterInSave(dto.getIsSaveObject());
            }
        }
    }


    public void updateByIdCard(TmpFamilyMemberEntity tmpMemberEntity) {
        tmpFamilyMemberWriteDao.updateByIdCard(tmpMemberEntity);
    }


    public void updateAreaCodeByFamilyId(String areaCode, String familyId) {
        tmpFamilyMemberWriteDao.updateAreaCodeByFamilyId(areaCode, familyId);
    }

    public void updateIsSaveByFamilyId(String familyId) {
        tmpFamilyMemberWriteDao.updateIsSaveByFamilyId(familyId);
    }


    public void changeMemberApply(String familyId, String orderId, Map<String,String> relationshipMap) {
        String applyMemberId = "";
        int count = 0;

        for(Map.Entry<String,String> entry:relationshipMap.entrySet()){
            if("1".equals(entry.getValue())){
                applyMemberId = entry.getKey();
                count++;
            }
        }
        if(count==0){
            throw new BizException(FailureCode.ERR_10051);
        }
        if(count>1){
            throw  new BizException(FailureCode.ERR_10052);
        }

        tmpFamilyMemberWriteDao.changApplyMember(familyId,applyMemberId);

        TmpFamilyMemberEntity memberEntity = familyMemberReadService.getById(applyMemberId);

        TmpOrderEntity order = new TmpOrderEntity();
        order.setId(orderId);
        order.setApplyName(memberEntity.getName());
        order.setApplyIdcard(memberEntity.getIdcard());
        orderWriteService.updateOrder(order);
    }

    public int copyFromLowerSource(String familyId,String newFamilyId){
        return tmpFamilyMemberWriteDao.copyFromLowerSource(familyId,newFamilyId);
    }


    public int copyFromLowerSplitSource(String familyId,String newFamilyId,String memberState){
        return tmpFamilyMemberWriteDao.copyFromLowerSplitSource(familyId,newFamilyId,memberState);
    }

    public int deleteMemberByIdCards(List<String> idCards) {
        return tmpFamilyMemberWriteDao.deleteMemberByIdCards(idCards);
    }

    public int deleteFamilyMemberByIdCard(String idCard) {
        return tmpFamilyMemberWriteDao.deleteFamilyMemberByIdCard(idCard);
    }

    public int deleteFamilyMemberByIdCardAndNoHasFamilyId(String idCard, String familyId) {
        return tmpFamilyMemberWriteDao.deleteFamilyMemberByIdCardAndNoHasFamilyId(idCard, familyId);
    }
}
